package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"time"

	"github.com/gorilla/websocket"
)

var (
	addr = flag.String("addr", "localhost:8888", "http service address")
	path = flag.String("path", "/user/msgSend", "websocket path")
)

func main() {
	flag.Parse()

	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	// 构造WebSocket URL
	url := fmt.Sprintf("ws://%s%s", *addr, *path)
	log.Printf("connecting to %s", url)

	// 创建连接
	dialer := websocket.DefaultDialer
	conn, _, err := dialer.Dial(url, nil)
	if err != nil {
		log.Fatal("dial error:", err)
	}
	defer conn.Close()

	done := make(chan struct{})
	inputChan := make(chan string)

	// 消息接收协程
	go func() {
		defer close(done)
		for {
			messageType, message, err := conn.ReadMessage()
			if err != nil {
				if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
					log.Printf("read error: %v", err)
				}
				return
			}

			switch messageType {
			case websocket.TextMessage:
				log.Printf("[Server] > %s", message)
			case websocket.BinaryMessage:
				log.Printf("Received binary data (length: %d)", len(message))
			case websocket.CloseMessage:
				log.Println("Connection closed")
				return
			}
		}
	}()

	// 消息发送协程
	go func() {
		reader := bufio.NewReader(os.Stdin)
		for {
			fmt.Print("[You] > ")
			text, _ := reader.ReadString('\n') // 读取输入直到换行符
			text = text[:len(text)-1]          // 去除换行符

			select {
			case <-done:
				return
			default:
				inputChan <- text
			}
		}
	}()

	// 主循环
	for {
		select {
		case <-done:
			return
		case msg := <-inputChan:
			// 发送文本消息
			err := conn.WriteMessage(websocket.TextMessage, []byte(msg))
			if err != nil {
				log.Println("write error:", err)
				return
			}
		case <-interrupt:
			log.Println("Received interrupt signal - closing connection")

			// 发送关闭消息
			err := conn.WriteMessage(websocket.CloseMessage,
				websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
			if err != nil {
				log.Println("write close error:", err)
				return
			}

			// 等待关闭完成
			select {
			case <-done:
			case <-time.After(time.Second):
			}
			return
		}
	}
}
